home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / gtlayout-source.lha / LT_MenuControlTagList.c < prev    next >
C/C++ Source or Header  |  1996-09-23  |  8KB  |  379 lines

  1. /*
  2. **    GadTools layout toolkit
  3. **
  4. **    Copyright © 1993-1996 by Olaf `Olsen' Barthel
  5. **        Freely distributable.
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #ifndef _GTLAYOUT_GLOBAL_H
  11. #include "gtlayout_global.h"
  12. #endif
  13.  
  14. #ifdef DO_MENUS
  15.  
  16. /****** gtlayout.library/LT_MenuControlTagList ******************************************
  17. *
  18. *   NAME
  19. *    LT_MenuControlTagList -- Manipulate menus, menu/submenu items (V11)
  20. *
  21. *   SYNOPSIS
  22. *    LT_MenuControlTagList(Window,Menu,Tags)
  23. *                           A0   A1     A2
  24. *
  25. *    VOID LT_MenuControlTagList(struct Window *,struct Menu *,struct TagItem *);
  26. *
  27. *    VOID LT_MenuControlTags(struct Window *,struct Menu *,...);
  28. *
  29. *   FUNCTION
  30. *    This routine provides a rather efficient way to set and to clear,
  31. *    to enable and to disable a number of menus, menu/submenu items
  32. *    all at once.
  33. *
  34. *    In v18 this routine was modified to disconnect a menu strip
  35. *    from a window if it is about to change checkmark states. In
  36. *    earlier releases or if a single menu is attached to several
  37. *    windows it is recommended that you disconnect the menu from
  38. *    the windows it is attached to before you call this routine.
  39. *
  40. *    As of v18 this routine is smart enough to handle menu
  41. *    mutual exclusion.
  42. *
  43. *   INPUTS
  44. *    Window - Pointer to Window this menu is attached to. Starting with
  45. *             gtlayout.library v16 this parameter may be NULL.
  46. *
  47. *    Menu - Pointer to Menu structure as returned by LT_NewMenuTagList.
  48. *
  49. *    Tags - Pointer to a list of tagitem values, as found
  50. *           in gtlayout.h
  51. *
  52. *
  53. *    Tags:
  54. *
  55. *    LAMN_ID (ULONG) - Unique ID of menu/menu item/submenu item to
  56. *        manipulate.
  57. *
  58. *    LAMN_Checked (BOOL) - Set the checkmark state of the
  59. *        menu/submenu item.
  60. *
  61. *    LAMN_Disabled (BOOL) - Set the availability state of the
  62. *        menu/menu item/submenu item.
  63. *
  64. *    LAMN_FullMenuNum (UWORD) - Intuition menu number of
  65. *        menu/submenu item to manipulate. You would pass the
  66. *        result of the FULLMENUNUM() macro here for the
  67. *        item in question. (V30)
  68. *
  69. *   RESULT
  70. *    none
  71. *
  72. *   EXAMPLE
  73. *    The following tagitem list will clear the checkmark and
  74. *    disable the menu item associated with ID 5 and set the
  75. *    checkmark for the item associated with ID 6:
  76. *
  77. *        LAMN_ID,         5,
  78. *          LAMN_Checked,  FALSE,
  79. *          LAMN_Disabled, TRUE,
  80. *        LAMN_ID,         6,
  81. *          LAMN_Checked,  TRUE,
  82. *        TAG_DONE
  83. *
  84. *   BUGS
  85. *    In library versions up to and including v17.2 this routine
  86. *    is broken. It won't do any harm, it just doesn't do what you
  87. *    want it to do.
  88. *
  89. *   SEE ALSO
  90. *    gtlayout.library/LT_NewMenuTagList
  91. *
  92. ******************************************************************************
  93. *
  94. */
  95.  
  96. VOID LIBENT
  97. LT_MenuControlTagList(REG(a0) struct Window *Window,REG(a1) struct Menu *IntuitionMenu,REG(a2) struct TagItem *Tags)
  98. {
  99.     RootMenu        *Root = (RootMenu *)((ULONG)IntuitionMenu - offsetof(RootMenu,Menu));
  100.     struct TagItem    *List,*Entry;
  101.     ULONG             ID;
  102.     MenuNode        *Menu;
  103.     ItemNode        *Item;
  104.     BOOL             GotIt;
  105.     BOOL             Disconnected = FALSE;
  106.  
  107.     if(!IntuitionMenu)
  108.         return;
  109.  
  110.     List = Tags;
  111.  
  112.         // Make sure that if window and menu are provided,
  113.         // the menu is attached to the window.
  114.  
  115.     if(Window && IntuitionMenu)
  116.     {
  117.         if(Window->MenuStrip != IntuitionMenu)
  118.             Window = NULL;
  119.     }
  120.  
  121.     while(Entry = NextTagItem(&List))
  122.     {
  123.         switch(Entry->ti_Tag)
  124.         {
  125.                 // We start with a menu/item/subitem ID
  126.  
  127.             case LAMN_ID:
  128.  
  129.                 GotIt = FALSE;
  130.  
  131.                 ID = (ULONG)Entry->ti_Data;
  132.  
  133.                     // Check if it's on the menu list
  134.  
  135.                 for(Menu = (MenuNode *)Root->MenuList.mlh_Head ; Menu->Node.mln_Succ ; Menu = (MenuNode *)Menu->Node.mln_Succ)
  136.                 {
  137.                     if(Menu->ID == ID)
  138.                     {
  139.                         GotIt = TRUE;
  140.  
  141.                         Item = NULL;
  142.  
  143.                         break;
  144.                     }
  145.                 }
  146.  
  147.                     // If it isn't, check the item/subitem list
  148.  
  149.                 if(!GotIt)
  150.                 {
  151.                     for(Item = (ItemNode *)Root->ItemList.mlh_Head ; Item->Node.mln_Succ ; Item = (ItemNode *)Item->Node.mln_Succ)
  152.                     {
  153.                         if(Item->ID == ID)
  154.                         {
  155.                             GotIt = TRUE;
  156.  
  157.                             Menu = NULL;
  158.  
  159.                             break;
  160.                         }
  161.                     }
  162.                 }
  163.  
  164.                     // Do nothing if none is found
  165.  
  166.                 if(!GotIt)
  167.                 {
  168.                     Menu = NULL;
  169.                     Item = NULL;
  170.                 }
  171.  
  172.                 break;
  173.  
  174.                 // We start with a menu/item/subitem ID
  175.  
  176.             case LAMN_FullMenuNum:
  177.  
  178.                 GotIt = FALSE;
  179.  
  180.                 ID = (ULONG)Entry->ti_Data;
  181.  
  182.                     // Check if it's on the menu list
  183.  
  184.                 for(Menu = (MenuNode *)Root->MenuList.mlh_Head ; Menu->Node.mln_Succ ; Menu = (MenuNode *)Menu->Node.mln_Succ)
  185.                 {
  186.                     if(Menu->MenuCode == ID)
  187.                     {
  188.                         GotIt = TRUE;
  189.  
  190.                         Item = NULL;
  191.  
  192.                         break;
  193.                     }
  194.                 }
  195.  
  196.                     // If it isn't, check the item/subitem list
  197.  
  198.                 if(!GotIt)
  199.                 {
  200.                     for(Item = (ItemNode *)Root->ItemList.mlh_Head ; Item->Node.mln_Succ ; Item = (ItemNode *)Item->Node.mln_Succ)
  201.                     {
  202.                         if(Item->MenuCode == ID)
  203.                         {
  204.                             GotIt = TRUE;
  205.  
  206.                             Menu = NULL;
  207.  
  208.                             break;
  209.                         }
  210.                     }
  211.                 }
  212.  
  213.                     // Do nothing if none is found
  214.  
  215.                 if(!GotIt)
  216.                 {
  217.                     Menu = NULL;
  218.                     Item = NULL;
  219.                 }
  220.  
  221.                 break;
  222.  
  223.                 // Fiddle with the checkmark
  224.  
  225.             case LAMN_Checked:
  226.  
  227.                 if(Item)
  228.                 {
  229.                         // Disconnect the window menu before we
  230.                         // change the states
  231.  
  232.                     if(Window && !Disconnected)
  233.                     {
  234.                         ClearMenuStrip(Window);
  235.  
  236.                         Disconnected = TRUE;
  237.                     }
  238.  
  239.                     if(Entry->ti_Data)
  240.                         Item->Item.Flags |=  CHECKED;
  241.                     else
  242.                         Item->Item.Flags &= ~CHECKED;
  243.  
  244.                         // Now check for mutual exclusion
  245.  
  246.                     if(Item->Item.MutualExclude && Entry->ti_Data)
  247.                     {
  248.                         ItemNode    *Node;
  249.                         ULONG         Exclude;
  250.                         LONG         Result;
  251.                         BOOL         IsSub;
  252.  
  253.                         Exclude = Item->Item.MutualExclude;
  254.  
  255.                             // Is the current item a submenu item?
  256.  
  257.                         if(SUBNUM(Item->MenuCode) == NOSUB)
  258.                             IsSub = FALSE;
  259.                         else
  260.                             IsSub = TRUE;
  261.  
  262.                             // Walk the item list back to the first list entry
  263.                             // in this menu/submenu
  264.  
  265.                         for(Node = Item ; Node->Node.mln_Pred ; Node = (ItemNode *)Node->Node.mln_Pred)
  266.                         {
  267.                                 // Extract the item number
  268.  
  269.                             if(IsSub)
  270.                                 Result = SUBNUM(Node->MenuCode);
  271.                             else
  272.                                 Result = ITEMNUM(Node->MenuCode);
  273.  
  274.                                 // Is this the first item?
  275.  
  276.                             if(!Result)
  277.                             {
  278.                                 LONG i,Mask,Value;
  279.  
  280.                                     // Now build a mask to extract the data
  281.                                     // that should remain constant for all
  282.                                     // items in this list.
  283.  
  284.                                 if(IsSub)
  285.                                     Mask = 0x07FF;    // menu-item + menu
  286.                                 else
  287.                                     Mask = 0x001F;    // menu
  288.  
  289.                                     // This is the constant value
  290.  
  291.                                 Value = Item->MenuCode & Mask;
  292.  
  293.                                     // Now we walk down the list
  294.  
  295.                                 for(i = 0 ; Node->Node.mln_Succ && i < 32 ; i++)
  296.                                 {
  297.                                         // Will this one be affected by the
  298.                                         // mutual exclusion stuff?
  299.  
  300.                                     if(Node != Item && (Node->Item.Flags & CHECKIT) && (Exclude & (1L << i)))
  301.                                         Node->Item.Flags &= ~CHECKED;
  302.  
  303.                                         // Move to the next item
  304.  
  305.                                     Node = (ItemNode *)Node->Node.mln_Succ;
  306.  
  307.                                         // Is this still the same menu/submenu?
  308.  
  309.                                     if((Node->MenuCode & Mask) != Value)
  310.                                         break;
  311.                                 }
  312.  
  313.                                 break;
  314.                             }
  315.                         }
  316.                     }
  317.                 }
  318.  
  319.                 break;
  320.  
  321.                 // Turn menus, submenus and items off or on
  322.  
  323.             case LAMN_Disabled:
  324.  
  325.                 if(Window)
  326.                 {
  327.                     LONG Code;
  328.  
  329.                     if(Item)
  330.                         Code = Item->MenuCode;
  331.                     else
  332.                         Code = Menu->MenuCode;
  333.  
  334.                     if(Entry->ti_Data)
  335.                         OffMenu(Window,Code);
  336.                     else
  337.                         OnMenu(Window,Code);
  338.                 }
  339.                 else
  340.                 {
  341.                     UWORD *Flags;
  342.  
  343.                     if(Item)
  344.                         Flags = &Item->Item.Flags;
  345.                     else
  346.                         Flags = &Menu->Menu.Flags;
  347.  
  348.                     if(Entry->ti_Data)
  349.                         *Flags &= ~ITEMENABLED;
  350.                     else
  351.                         *Flags |= ITEMENABLED;
  352.                 }
  353.  
  354.                 break;
  355.         }
  356.     }
  357.  
  358.         // Reconnect the menu strip if necessary
  359.  
  360.     if(Disconnected)
  361.         ResetMenuStrip(Window,IntuitionMenu);
  362. }
  363.  
  364.  
  365. /*****************************************************************************/
  366.  
  367.  
  368. VOID
  369. LT_MenuControlTags(struct Window *Window,struct Menu *Menu,...)
  370. {
  371.     va_list VarArgs;
  372.  
  373.     va_start(VarArgs,Menu);
  374.     LT_MenuControlTagList(Window,Menu,(struct TagItem *)VarArgs);
  375.     va_end(VarArgs);
  376. }
  377.  
  378. #endif    /* DO_MENUS */
  379.